﻿using System.Linq;
using JetBrains.Annotations;
using JetBrains.Metadata.Reader.API;
using JetBrains.ReSharper.Feature.Services.CSharp.Bulbs;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Modules;

namespace MugenMvvmToolkit.ReSharper.Infrastructure
{
    public class EventProvider
    {
        #region Fields

        private readonly TypeProvider _typeProvider;

        #endregion

        #region Constructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="EventProvider" /> class.
        /// </summary>
        private EventProvider([NotNull] IPsiModule psiModule, [NotNull] IModuleReferenceResolveContext resolveContext)
        {
            _typeProvider = TypeProvider.Create(psiModule, resolveContext);
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="EventProvider" /> class.
        /// </summary>
        private EventProvider([NotNull] ICSharpContextActionDataProvider provider)
        {
            _typeProvider = TypeProvider.Create(provider);
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="EventProvider" /> class.
        /// </summary>
        private EventProvider(TypeProvider typeProvider)
        {
            _typeProvider = typeProvider;
        }

        #endregion

        #region Properties

        [CanBeNull]
        public IEvent CloseableViewModelInterfaceClosing
        {
            get { return FindEvent(_typeProvider.NotifyViewModelClosingInterface, "Closing"); }
        }

        [CanBeNull]
        public IEvent CloseableViewModelInterfaceClosed
        {
            get { return FindEvent(_typeProvider.CloseableViewModelInterface, "Closed"); }
        }

        #endregion

        #region Methods

        public static EventProvider Create([NotNull] IPsiModule psiModule,
            [NotNull] IModuleReferenceResolveContext resolveContext)
        {
            return new EventProvider(psiModule, resolveContext);
        }

        public static EventProvider Create([NotNull] ICSharpContextActionDataProvider provider)
        {
            return new EventProvider(provider);
        }

        public static EventProvider Create(TypeProvider typeProvider)
        {
            return new EventProvider(typeProvider);
        }

        [CanBeNull]
        private static IEvent FindEvent(IDeclaredType type, string eventName)
        {
            ITypeElement typeElement = type.GetTypeElement();
            if (typeElement == null)
                return null;
            return typeElement
                .Events
                .SingleOrDefault(method => method.ShortName == eventName);
        }

        #endregion
    }
}